﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace fes
{
    public delegate void ChangeIndicator(Indicator ind, int indnum);
    public delegate void CancelChange();

    public partial class ExpertSet : Form
    {
        ExpertSystem es;
        int modyfied=-1;
        int IndMod=-1;
        bool ind1modyfied = false;
        bool ind2modyfied = false;
        private List<Indicator> indicators = new List<Indicator>();
        private List<FuzzyAssociativeMemory> fams = new List<FuzzyAssociativeMemory>();

        public ExpertSet()
        {
          Double d = 0.3;
          es = OurGlobals.MyExpertSystem;
          InitializeComponent();

          txtTradingCost.Text = d.ToString();
        }

        private void NewConfiguration_Click(object sender, EventArgs e)
        {
            EnableInterface(false);
            AcceptNumber.Enabled = true;
            ExpertSystemName.Enabled = true;

        }

        private void EnableInterface(bool param) 
        {
            Indicator1.Enabled = param;
            Indicator1.Text = " ";
            Indicator2.Enabled = param;
            Indicator2.Text = " ";
            Indicator2Mod.Enabled = param;
            Indicator1Mod.Enabled = param;
            IndicatorList.Enabled = param;
      
            //FAM.Enabled = param;
            //SaveExpertSet.Enabled = param;
            //LoadExpertSet.Enabled = param;
            AcceptNumber.Enabled = param;
            NewConfiguration.Enabled = param;
            ExpertSystemName.Enabled = param;

            AddPair.Enabled = param;
            DeletePair.Enabled = param;
            SavePair.Enabled = param;
      
        }

        private void AcceptNumber_Click(object sender, EventArgs e)
        {
            if(ExpertSystemName.TextLength == 0) return;
            AddPair.Enabled = true;
            IndicatorList.Enabled = true;

            ExpertSystemName.Enabled = false;
            AcceptNumber.Enabled = false;
            es = new ExpertSystem(ExpertSystemName.Text);


            
        }

        private void AddPair_Click(object sender, EventArgs e)
        {
            if (es.Name.Length == 0) return;
            Dictionary<String, Object> IndParams = new Dictionary<string, object>();
            IndParams.Add("n", 5);

            SavePair.Enabled = true;
            DeletePair.Enabled = true;
            //FAM.Enabled = true;
            Indicator1Mod.Enabled = true;
            Indicator2Mod.Enabled = true;
            Indicator1.Enabled = true;
            Indicator2.Enabled = true;

            RSI RSIind = new RSI(IndParams);

            RSIind.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
            RSIind.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
            RSIind.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        

            CCI CCIind = new CCI(IndParams);

            CCIind.addFuzzySet(new double[2] { -150.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
            CCIind.addFuzzySet(new double[3] { -125.0, 0.0, 125.0 }, "M", FuzzySet.FuzzySetType.Triangle);
            CCIind.addFuzzySet(new double[2] { 50.0, 150.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

            indicators.Add(RSIind);
            indicators.Add(CCIind);
            fams.Add(new FuzzyAssociativeMemory(RSIind, CCIind));
            modyfied = fams.Count - 1;
            IndicatorList.Items.Add(indicators[indicators.Count - 2].name + " - " + indicators[indicators.Count - 1].name);
            Indicator1.SelectedIndex = 0;
            Indicator2.SelectedIndex = 1;

            ind1modyfied = false;
            ind2modyfied = false;

        }

        private void IndicatorList_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (IndicatorList.SelectedIndex == -1) return;
            modyfied = IndicatorList.SelectedIndex;
            Indicator1.SelectedItem = indicators[modyfied * 2].name;
            Indicator2.SelectedItem = indicators[modyfied * 2 + 1].name;

            SavePair.Enabled = true;
            DeletePair.Enabled = true;


        }

        private void SavePair_Click(object sender, EventArgs e)
        {
            if((modyfied <0) || (modyfied >= fams.Count)) return;

            Indicator newInd1 = new Indicator("Uknown"), newInd2 = new Indicator("Unknown") ;
            Dictionary<String, Object> IndParams = new Dictionary<string, object>();
            IndParams.Add("n", 5);
           

            if (ind1modyfied)
            {
                switch (Indicator1.SelectedIndex)
                {
                    case 0: newInd1 = new RSI(IndParams);
                        newInd1.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd1.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd1.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    case 1: newInd1 = new CCI(IndParams);
                        newInd1.addFuzzySet(new double[2] { -150.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd1.addFuzzySet(new double[3] { -125.0, 0.0, 125.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd1.addFuzzySet(new double[2] { 50.0, 150.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    case 2: newInd1 = new ROC(IndParams);
                        newInd1.addFuzzySet(new double[2] { -5.0, -1.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd1.addFuzzySet(new double[3] { -2.5, 0.0, 2.5 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd1.addFuzzySet(new double[2] { 1.0, 5.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    default: newInd1 = new RSI(IndParams);
                        newInd1.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd1.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd1.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;

                }

        

                indicators[modyfied * 2] = newInd1;
            }
            if (ind2modyfied)
            {
                switch (Indicator2.SelectedIndex)
                {
                    case 0: newInd2 = new RSI(IndParams);
                        newInd2.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd2.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd2.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    case 1: newInd2 = new CCI(IndParams);
                        newInd2.addFuzzySet(new double[2] { -150.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd2.addFuzzySet(new double[3] { -125.0, 0.0, 125.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd2.addFuzzySet(new double[2] { 50.0, 150.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    case 2: newInd2 = new ROC(IndParams);
                        newInd2.addFuzzySet(new double[2] { -5.0, -1.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd2.addFuzzySet(new double[3] { -2.5, 0.0, 2.5 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd2.addFuzzySet(new double[2] { 1.0, 5.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;
                    default: newInd2 = new RSI(IndParams);
                        newInd2.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
                        newInd2.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
                        newInd2.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);
                        break;

                }

                indicators[modyfied * 2 + 1] = newInd2;
            }

            IndicatorList.Items[modyfied] = indicators[modyfied * 2].name + " - " + indicators[modyfied * 2 + 1].name;

            ind1modyfied = false;
            ind2modyfied = false;

        }

        private void DeletePair_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Czy napewno chcesz usunąć tą parę?", "Potwierdź", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
            if (dr == DialogResult.No) return;
            indicators.RemoveRange(modyfied * 2,2);
            es.FAMs.RemoveAt(modyfied);
            IndicatorList.Items.RemoveAt(modyfied);
        }

        private void IndicatorGet(Indicator item, int indnum)
        {
          indicators[modyfied * 2 + indnum] = item;
          CancelGet();
        }

        private void CancelGet()
        {
            IndMod = -1;
            this.Enabled = true;
            ExpertSystemName.Enabled = false;
            AcceptNumber.Enabled = false;


        }
        private void Indicator1Mod_Click(object sender, EventArgs e)
        {
            if (IndMod != -1) return;
            IndMod = 0;
            this.Enabled = false;
            FuzzyParams fp = new FuzzyParams(indicators[modyfied * 2],0);
            fp.SendIndicator = new ChangeIndicator(IndicatorGet);
            fp.CancelSendIndicator = new CancelChange(CancelGet);
            fp.Show();
        }

        private void Indicator2Mod_Click(object sender, EventArgs e)
        {
            if (IndMod != -1) return;
            IndMod = 1;
            this.Enabled = false;
            FuzzyParams fp = new FuzzyParams(indicators[modyfied * 2+1],1);
            fp.SendIndicator = new ChangeIndicator(IndicatorGet);
            fp.CancelSendIndicator = new CancelChange(CancelGet);
            fp.Show();
        }

        private void Indicator1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ind1modyfied = true;
            
        }

        private void Indicator2_SelectedIndexChanged(object sender, EventArgs e)
        {
            ind2modyfied = true;
        }

        private void ExpertSet_Load(object sender, EventArgs e)
        {
            LoadExpertSystem();

        }

        private void LoadExpertSystem()
        {
            IndicatorList.Items.Clear();
            ExpertSystemName.Text = es.Name;
            for (int i = 0; i < indicators.Count / 2; i++)
            {
                IndicatorList.Items.Add(es.getIndicator(i * 2) + " - " + es.getIndicator(i * 2 + 1));
            }
            EnableInterface(false);
            IndicatorList.Enabled = true;
            AddPair.Enabled = true;
            NewConfiguration.Enabled = true;
            LoadExpertSet.Enabled = true;
            SaveExpertSet.Enabled = true;
        }

        private void SaveAll_Click(object sender, EventArgs e)
        {
          //TODO:
          // wydaje mi sie, ze dopiero tutaj powinna byc wypelniona klasa ExpertSystem po wczesniej walidacji:
          // 1. czy jest wybrany symbol uczacy?
          // 2. czy sa wybrane symbole do symulacji
          // 3. czy sa zdefiniowane parametry systemu: wskazniki itp.
          if (lstSymbols.Items.Count == 0)
          {
            MessageBox.Show("Wybierz conajmniej jeden symbol");
            return;
          }
          if (!(fams.Count > 1))
          {
            MessageBox.Show("Zdefiniuj conajmniej dwie pary");
          }

          List<String> syms = new List<string>();
          
          
          try
          {
            foreach (StockData sd in OurGlobals.symbolsSD)
              syms.Add(sd.getSymbol());
            OurGlobals.MyExpertSystem = new ExpertSystem(ExpertSystemName.Text, syms); 
            OurGlobals.MyExpertSystem.InitialCash = Double.Parse(txtInitialCash.Text);
            OurGlobals.MyExpertSystem.TradingCost = Double.Parse(txtTradingCost.Text) / 100.0;
            OurGlobals.MyExpertSystem.TeachNetAfter = Int32.Parse(txtTeachAfter.Text);
            for (int i = 0; i < indicators.Count / 2; i++)
              OurGlobals.MyExpertSystem.AddIndicatorPair(indicators[2 * i], indicators[2 * i + 1]);
            OurGlobals.MyExpertSystem.SetNeuralNetwork(3, OurGlobals.MyExpertSystem.TeachNetAfter);
            OurGlobals.MyExpertSystem.IsSet = true;
            Close();
          }
          catch(Exception ex)
          {
            MessageBox.Show(ex.Message);
          }
        }

        private void btnTeachingSymbol_Click(object sender, EventArgs e)
        {
          OpenFileDialog d = new OpenFileDialog();
          d.Title = "Wybierz zestaw treningowy";
          d.InitialDirectory = Directory.GetCurrentDirectory() + "\\test";
          d.Filter = "Pliki MST (*mst)|*.mst";
          if (d.ShowDialog() != DialogResult.OK)
            return;

          OurGlobals.teachingSD = new StockData();
          OurGlobals.teachingSD.readFromFile(d.FileName);
          txtTeachingSymbol.Text = OurGlobals.teachingSD.getSymbol();

        }

        private void btnAddSymbol_Click(object sender, EventArgs e)
        {
          OpenFileDialog d = new OpenFileDialog();
          d.Multiselect = true;
          d.Title = "Wybierz zestaw treningowy";
          d.InitialDirectory = Directory.GetCurrentDirectory() + "\\test";
          d.Filter = "Pliki MST (*mst)|*.mst";
          if (d.ShowDialog() != DialogResult.OK)
            return;
          foreach (String file in d.FileNames)
          {
            StockData s = new StockData();
            s.readFromFile(file);
            OurGlobals.symbolsSD.Add(s);
            lstSymbols.Items.Add(s.getSymbol());
          }
          lstSymbols.Sorted = true;
        }

        private void btnRemoveSymbol_Click(object sender, EventArgs e)
        {
          while (lstSymbols.SelectedItems.Count > 0)
          {
            String name = (String)lstSymbols.SelectedItem;
            foreach (StockData sd in OurGlobals.symbolsSD)
            {
              if (sd.getSymbol() == name)
              {
                OurGlobals.symbolsSD.Remove(sd);
                break;
              }
            }
            lstSymbols.Items.Remove(lstSymbols.SelectedItem);
          }
        }

        public int getNumberOfTeachingSessions()
        {
          return Int32.Parse(txtNumberOfTeachingSessions.Text);
        }

    }
}
